//
//  SelfDiagnosisViewModel.m
//  MobileChecker
//
//  Created by Lymons on 15-1-7.
//  Copyright (c) 2015年 Lymons. All rights reserved.
//

#import "SelfDiagnosisViewModel.h"
#import "VibrationDiagnosisService.h"
#import "RecordDiagnosisService.h"
#import "SoundDiagnosisService.h"
#import "TouchDiagnosisService.h"
#import "ScreenDiagnosisService.h"
#import "CameraDiagnosisService.h"
#import "SystemUtils.h"

#import <MobileCoreServices/UTCoreTypes.h>

@interface SelfDiagnosisViewModel ()

@property (strong, nonatomic) BaseSelfDiagnosisService *services;
@property (assign, nonatomic) DiagnosisCheckResult checkResult;
@property (nonatomic) RACSignal *validCheckSignal;
@property (nonatomic) RACSignal *validCompletedSignal;

@end

@implementation SelfDiagnosisViewModel

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self initialize];
        [self setupSignals];
    }
    return self;
}

- (instancetype)initWithServices:(BaseSelfDiagnosisService *)services
{
    self = [super init];
    if (self) {
        _services = services;
        [self initialize];
        [self setupSignals];
    }
    return self;
}

- (void)initialize
{
    self.totalSeconds = 5;
    _checkCompleted = NO;
    _checkResult = DiagnosisCheckResultNoCheck;
    headerCompletedString = nil;
    headerInitialString = nil;
}

- (void)setTotalSeconds:(NSUInteger)totalSeconds
{
    _totalSeconds = totalSeconds;
    _leftSeconds = totalSeconds;
}

- (void)checkDidCompleted
{
    headerCompletedString ? self.headerString = headerCompletedString : nil;
    self.leftSeconds = self.totalSeconds;
}

- (void)resultDidReceived:(DiagnosisCheckResult)result
{
    self.checkResult = result;
    self.enableCheck = (result == DiagnosisCheckResultNoCheck);
}

//- (void)setEnableCheck:(BOOL)enableCheck
//{
//    _enableCheck = enableCheck;
//    [self initExcuteCheck];
//}

- (void)setupSignals
{
    self.validCompletedSignal =
    [[RACObserve(self, checkCompleted)
      filter:^BOOL(NSNumber* value) {
          return [value boolValue];
      }]
     distinctUntilChanged];
    
    [self.validCompletedSignal subscribeNext:^(id x) {
        NSLog(@"checking is completed %@", x);
    }];
    
    self.validCheckSignal =
    [[RACObserve(self, enableCheck)
      filter:^BOOL(NSNumber* value) {
          return [value boolValue];
      }]
     distinctUntilChanged];
    
    [self.validCheckSignal subscribeNext:^(id x) {
        NSLog(@"checking is valid %@", x);
    }];
    
    RACChannelTo(self.services, leftSeconds) = RACChannelTo(self, leftSeconds);
    
    [self initExcuteCheck];
}

- (void)initExcuteCheck
{
    @weakify(self);
    self.executeCheck = [[RACCommand alloc] initWithEnabled:self.validCheckSignal
                                                signalBlock:^RACSignal *(id input) {
                                                    @strongify(self);
                                                    return [[self.services checkSignal:self.leftSeconds] doNext:^(id x) {
                                                        self.checkCompleted = YES;
                                                        [self checkDidCompleted];
                                                    }];
                                                }];
}

- (RACCommand *)makeCommandWithBlock:(OkNgBlock)okngBlock simple:(BOOL)okng
{
    return [self makeCommandWithBlock:okngBlock detail:okng?DiagnosisCheckResultOk:DiagnosisCheckResultNg];
}

- (RACCommand *)makeCommandWithBlock:(OkNgBlock)okngBlock detail:(DiagnosisCheckResult)result
{
    @weakify(self);
    return [[RACCommand alloc] initWithEnabled:self.validCompletedSignal
                                   signalBlock:^RACSignal *(id input) {
                                       @strongify(self);
                                       [self.services endCheckOnTimer:nil];
                                       [self resultDidReceived:result];
                                       if (okngBlock != NULL) {
                                           okngBlock(result == DiagnosisCheckResultOk);
                                       }
                                       return [RACSignal empty];
                                   }];
}

- (void)executeTheCheckCommand:(id)input
{
    [self.executeCheck execute:input];
}

- (void)completeTheCheckCommand
{
    [self.services endCheckOnTimer:nil];
}

#pragma mark -
#pragma mark Private

- (RACCommand *)makeOkCommand:(OkNgBlock)block
{
    return [self makeCommandWithBlock:block simple:YES];
}

- (RACCommand *)makeNgCommand:(OkNgBlock)block
{
    return [self makeCommandWithBlock:block simple:NO];
}

@end

@implementation DiagnosisVibrationViewModel

- (instancetype)init
{
    return [super initWithServices:[[VibrationDiagnosisService alloc] init]];
}

- (void)initialize
{
    [super initialize];
    self.headerString = @"バイブ機能を実行しています。\nバイブを感じたら「OK」ボタンを押してください。";
    self.enableCheck = [CheckResultUserDefaults standardUserDefaults].vibrationCheckResult == DiagnosisCheckResultNoCheck;
}

- (void)resultDidReceived:(DiagnosisCheckResult)result
{
    [super resultDidReceived:result];
    [CheckResultUserDefaults standardUserDefaults].vibrationCheckResult = result;
}

@end

@implementation DiagnosisRecordViewModel

- (instancetype)init
{
    return [super initWithServices:[[RecordDiagnosisService alloc] init]];
}

- (void)initialize
{
    [super initialize];
    self.enableCheck = [CheckResultUserDefaults standardUserDefaults].vibrationCheckResult == DiagnosisCheckResultNoCheck;
}

- (void)setupSignals
{
    [super setupSignals];
    RecordDiagnosisService *recordService = (RecordDiagnosisService *)self.services;
    RAC(self, volumeDbString) = RACObserve(recordService, volumeDbString);
}

- (void)resultDidReceived:(DiagnosisCheckResult)result
{
    [super resultDidReceived:result];
    [CheckResultUserDefaults standardUserDefaults].recordCheckResult = result;
}

@end


@implementation DiagnosisSoundViewModel

- (instancetype)init
{
    return [super initWithServices:[[SoundDiagnosisService alloc] init]];
}

- (instancetype)initWithType:(SoundDiagnosisServiceType)type
{
    return [super initWithServices:[[SoundDiagnosisService alloc] initWithSoundDiagnosisServiceType:type]];
}

- (void)initialize
{
    [super initialize];
    self.enableCheck = [CheckResultUserDefaults standardUserDefaults].soundCheckResult == DiagnosisCheckResultNoCheck;
    self.totalSeconds = 0;
    RAC(self, toastMessage) = RACObserve(((SoundDiagnosisService *)self.services), toastMessage);
}

- (void)resultDidReceived:(DiagnosisCheckResult)result
{
    [super resultDidReceived:result];
    [CheckResultUserDefaults standardUserDefaults].soundCheckResult = result;
}

- (RACSignal *)requestRecordPermission
{
    return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
        if (BELOWIOS7) {
            [subscriber sendNext:[NSNumber numberWithBool:YES]];
            
        } else if ([[AVAudioSession sharedInstance] respondsToSelector:@selector(requestRecordPermission:)]) {
            [[AVAudioSession sharedInstance] performSelector:@selector(requestRecordPermission:) withObject:^(BOOL granted) {
                [subscriber sendNext:[NSNumber numberWithBool:granted]];
            }];
        }
        
        return [RACDisposable disposableWithBlock:^{
            
        }];
    }];
}

@end


@implementation DiagnosisTouchViewModel

- (instancetype)init
{
    return [super initWithServices:[[TouchDiagnosisService alloc] init]];
}

- (void)initialize
{
    [super initialize];
    self.enableCheck = [CheckResultUserDefaults standardUserDefaults].touchCheckResult == DiagnosisCheckResultNoCheck;
    self.headerString = @"画面をなぞって線が書けるか確認してください。\n画面をタップすると、開始します。";
    headerCompletedString = @"正しく描けましたか？\nもう一度試す場合は、画面をタップしてください。";
}

- (void)resultDidReceived:(DiagnosisCheckResult)result
{
    [super resultDidReceived:result];
    [CheckResultUserDefaults standardUserDefaults].touchCheckResult = result;
}

@end

@implementation DiagnosisScreenViewModel

- (instancetype)init
{
    return [super initWithServices:[[ScreenDiagnosisService alloc] init]];
}

- (void)initialize
{
    [super initialize];
    self.enableCheck = [CheckResultUserDefaults standardUserDefaults].screenCheckResult == DiagnosisCheckResultNoCheck;
    self.headerString = @"画面をスワイプし、ドット抜け、画面ヤケや色ムラが無いかを確認してください。\n画面をタップすると、開始します。\n\n診断を終了する場合は、ダブルタップしてください。";
    headerCompletedString = @"綺麗に表示されましたか？\nもう一度試す場合は、画面をダブルタップしてください。";
}

- (void)resultDidReceived:(DiagnosisCheckResult)result
{
    [super resultDidReceived:result];
    [CheckResultUserDefaults standardUserDefaults].screenCheckResult = result;
}

@end



